﻿using System;
using System.Collections.Generic;


namespace SpiritEngine
{
    public abstract class AComponent
    {

        // MEMBER VARIABLES
        // ------------------------------------------------------------------------------------------------------------------------

        // Keep track of the number of each type of component that have been
        // created, so we can generate a unique name for each component.
        static Dictionary<Type, int> m_dictComponentTypeCounts = new Dictionary<Type, int>();

        bool m_bLoaded = false;

        int m_nDrawOrder;

        string m_strName;

        GameScreen m_gsParentGameScreen;
        AComponent m_ParentComponent;



        // CONSTRUCTORS
        // ------------------------------------------------------------------------------------------------------------------------

        public AComponent()
        {
            GenerateUniqueName();
        } // end AComponent::AComponent()


        // PRIVATE/PROTECTED METHODS
        // ------------------------------------------------------------------------------------------------------------------------

        // Generate a unqiue name for the component simply using the type name
        // and the number of that component type that have been created.
        private void GenerateUniqueName()
        {
            Type t = this.GetType();


            if (!m_dictComponentTypeCounts.ContainsKey(t))
            {
                m_dictComponentTypeCounts.Add(t, 0);
            }


            m_dictComponentTypeCounts[t]++;

            this.Name = t.Name + m_dictComponentTypeCounts[t];

        } // end void AComponent::GenerateUniqueName()

        protected virtual void Load()
        {
        } // end void AComponent::Load()


        // METHODS
        // ------------------------------------------------------------------------------------------------------------------------

        public void LoadComponent()
        {
            if (!m_bLoaded)
                Load();

            m_bLoaded = true;

        } // end void AComponent::LoadComponent()

        public virtual void Update()
        {
        } // end void AComponent::Update()
        
        public virtual void Draw()
        {
        } // end void AComponent::Draw()



        // DEBUG METHODS
        // ------------------------------------------------------------------------------------------------------------------------

#if (DEBUG)
        // put all debug methods in here...
#endif


        // PROPERTIES
        // ------------------------------------------------------------------------------------------------------------------------

        public int DrawOrder
        {
            get
            {
                return m_nDrawOrder;
            }
            set
            {
                this.m_nDrawOrder = value;

                if (m_gsParentGameScreen != null)
                {
                    m_gsParentGameScreen.PutComponentInOrder(this);
                }
            }
        } // end property DrawOrder

        public bool Loaded
        {
            get
            {
                return m_bLoaded;
            }
        } // end property Loaded

        public string Name
        {
            get
            {
                return m_strName;
            }
            set
            {
                // Make sure we have a valid name before allowing it to be changed
                if (string.IsNullOrEmpty(value))
                {
                    throw new Exception("Component name must not be null "
                        + "and must me longer than 0 characters in length!");
                }
                else
                {
                    m_strName = value;
                }
            }
        } // end property Name

        public GameScreen ParentGameScreen
        {
            get
            {
                return m_gsParentGameScreen;
            }
            set
            {
                if (m_gsParentGameScreen == value)
                    return;

                if (m_gsParentGameScreen != null)
                    m_gsParentGameScreen.RemoveComponent(this);

                m_gsParentGameScreen = value;

                if (value != null)
                    m_gsParentGameScreen.AddComponent(this);
            }
        } // end property Parent

        public AComponent ParentComponent
        {
            get
            {
                return m_ParentComponent;
            }
            set
            {
                m_ParentComponent = value;
            }
        } // end property ParentComponent


        // EVENTS
        // ------------------------------------------------------------------------------------------------------------------------


    } // end class AComponent

}
